name: Build Docker Image

on:
  push:
    branches:
      - master
  release:
    types: [published]
  pull_request:
    paths:
      - .github/workflows/dockerimage.yml
      - Dockerfile
      - .dockerignore
      - pyproject.toml
      - .github/workflows/dockerimage.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.run_number || github.ref }}
  cancel-in-progress: true

env:
  DOCKER_HUB_BASE_NAME: optuna/optuna

jobs:

  dockerimage:

    runs-on: ubuntu-latest

    # TODO (nzw0301): Remove `exclude` once integration works with Python 3.11.
    strategy:
      matrix:
        python_version: ['3.7', '3.8', '3.9', '3.10', '3.11']
        build_type: ['', 'dev']  # "dev" installs all the dependencies including pytest.
        exclude:
        - python_version: '3.7'
          build_type: 'dev'
        - python_version: '3.11'
          build_type: 'dev'

    # This action cannot be executed in the forked repository.
    if: github.repository == 'optuna/optuna'
    steps:
    - uses: actions/checkout@v4

    - name: Set ENV
      run: |
        export TAG_NAME="py${{ matrix.python_version }}"
        if [ "${{ github.event_name }}" = 'release' ]; then
          export TAG_NAME="${{ github.event.release.tag_name }}-${TAG_NAME}"
        fi
        if [ "${{matrix.build_type}}" = 'dev' ]; then
          export TAG_NAME="${TAG_NAME}-dev"
        fi
        echo "HUB_TAG=${DOCKER_HUB_BASE_NAME}:${TAG_NAME}" >> $GITHUB_ENV

    - name: Build the Docker image
      run: |
        if [ "${{ github.event_name }}" = 'release' ]; then
          # Cache is not available because the image tag includes the Optuna version.
          CACHE_FROM=""
        else
          CACHE_FROM="--cache-from=${HUB_TAG}"
        fi
        docker build ${CACHE_FROM} . --build-arg PYTHON_VERSION=${{ matrix.python_version }} --build-arg BUILD_TYPE=${{ matrix.build_type }} --file Dockerfile --tag "${HUB_TAG}"
      env:
        DOCKER_BUILDKIT: 1

    - name: Output installed packages
      run: |
        docker run "${HUB_TAG}" sh -c "pip freeze --all"
    - name: Output dependency tree
      run: |
        docker run "${HUB_TAG}" sh -c "pip install pipdeptree && pipdeptree"

    - name: Verify the built image
      run: |
        docker run "${HUB_TAG}" optuna --version

    - name: Login & Push to Docker Hub
      if: ${{ github.event_name != 'pull_request' }}
      env:
        DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
      run: |
        echo "${DOCKER_HUB_TOKEN}" | docker login -u optunabot --password-stdin
        docker push "${HUB_TAG}"
